#include "preHeader.h"
#include "MapServerSession.h"
#include "MapServerSessionHandler.h"
#include "GameServerSession.h"
#include "SocialServerSession.h"
#include "MapServerMgr.h"
#include "ClientMgr.h"
#include "GateServer.h"
#include "network/ConnectionManager.h"
#include "Game/TransMgr.h"

bool MapServerSession::m_handlerFlags[GAME_OPCODE::CSMSG_COUNT];

MapServerSession::MapServerSession(uint32 msSN, uint32 gsIdx,
	const std::string& host, const std::string& port)
: Session("MapServerSession")
, m_msSN(msSN)
, m_gsIdx(gsIdx)
, m_host(host)
, m_port(port)
, m_isCancelled(false)
{
}

MapServerSession::~MapServerSession()
{
}

void MapServerSession::CheckConnection()
{
	const auto& connPrePtr = GetConnection();
	if (connPrePtr && connPrePtr->IsActive()) {
		return;
	}
	if (!IsStatus(Idle)) {
		return;
	}

	if (IsCancelled()) {
		if (IsIndependent()) {
			sMapServerMgr.RemoveMapServer(this);
			delete this;
		}
		return;
	}

	auto connPtr = sConnectionManager.NewConnection(*this);
	connPtr->AsyncConnect(m_host, m_port);

	sSessionManager.AddSession(this);
}

void MapServerSession::TransPacket(ObjGUID guid, const INetPacket& pck)
{
	NetPacket trans(CGM_TRANS_PLAYER_PACKET);
	trans << guid;
	PushSendPacket(trans, pck);
}

int MapServerSession::HandlePacket(INetPacket *pck)
{
	return sMapServerSessionHandler.HandlePacket(this, *pck);
}

void MapServerSession::OnConnected()
{
	NetPacket req(CGM_REGISTER);
	req << sGameServerSession.GetServerId() << sGameServerSession.sn()
		<< m_msSN << m_gsIdx;
	PushSendPacket(req);
	Session::OnConnected();
}

void MapServerSession::OnManaged()
{
	sTransMgr.AddMapServer(this);
	Session::OnManaged();
}

void MapServerSession::OnShutdownSession()
{
	WLOG("Close MapServerSession [msSN:%u gsIdx:%u].", m_msSN, m_gsIdx);
	Session::OnShutdownSession();
}

void MapServerSession::DeleteObject()
{
	ClearRecvPacket();
	ClearShutdownFlag();
	SetStatus(Idle);
}

void MapServerSession::OnRecvPacket(INetPacket *pck)
{
	switch (pck->GetOpcode()) {
	case SGM_TRANS_CLIENT_PACKET:
		TransClientPacket(pck);
		delete pck;
		break;
	case SGM_TRANS_MAP_SERVER_PACKET:
		TransMapServerPacket(pck);
		delete pck;
		break;
	case SGM_TRANS_SOCIAL_SERVER_PACKET:
		TransSocialServerPacket(pck);
		delete pck;
		break;
	default:
		Session::OnRecvPacket(pck);
		break;
	}
}

void MapServerSession::TransClientPacket(INetPacket *pck) const
{
	auto pSession = sTransMgr.GetClient(pck->Read<uint32>());
	if (pSession != NULL) {
		pSession->PushSendPacket(pck->CastReadableStringView());
	}
}

void MapServerSession::TransMapServerPacket(INetPacket *pck) const
{
	auto pSession = sTransMgr.GetMapServer(pck->Read<uint32>());
	if (pSession != NULL) {
		pSession->PushSendPacket(pck->CastReadableStringView());
	}
}

void MapServerSession::TransSocialServerPacket(INetPacket *pck) const
{
	sSocialServerSession.PushSendPacket(pck->CastReadableStringView());
}

void MapServerSession::Cancel()
{
	sTransMgr.RemoveMapServer(this);
	m_isCancelled = true;
	KillSession();
}

void MapServerSession::Reuse()
{
	m_isCancelled = false;
}

int MapServerSessionHandler::HandleRegisterResp(MapServerSession *pSession, INetPacket &pck)
{
	pck.Take(pSession->m_handlerFlags, sizeof(pSession->m_handlerFlags));
	NLOG("Register to MapServer Success As [msSN:%u gsIdx:%u].",
		pSession->m_msSN, pSession->m_gsIdx);
	return SessionHandleSuccess;
}

int MapServerSessionHandler::HandlePushPacketToAllClient(MapServerSession *pSession, INetPacket &pck)
{
	sClientMgr.BroadcastPacket2AllClient(pck.UnpackPacket());
	return SessionHandleSuccess;
}
